package com.handle.common.redis.generator;

import lombok.AllArgsConstructor;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author zq
 */
@Component
@AllArgsConstructor
public class RedisIdGenerator {

    private final RedissonClient redissonClient;

    /**
     * @param key 生成主键key
     * @param value 指定值
     * @param expireTime 过期时间
     */
    public void set(String key, Long value, Date expireTime) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        atomicLong.getAndAdd(value);
        atomicLong.expireAt(expireTime);
    }

    /**
     * @param key 生成主键key
     * @param value 指定值
     * @param timeout 过期时间
     * @param unit 单位
     */
    public void set(String key, int value, long timeout, TimeUnit unit) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        atomicLong.set(value);
        atomicLong.expire(timeout, unit);
    }

    /**
     * @param key 生成主键key
     * @return 自增值
     */
    public long generate(String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.incrementAndGet();
    }

    /**
     * @param key 生成主键key
     * @param expireTime 过期时间
     * @return 自增值
     */
    public long generate(String key, Date expireTime) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        atomicLong.expireAt(expireTime);
        return atomicLong.incrementAndGet();
    }

    /**
     * @param key 生成主键key
     * @param increment 递增值
     * @return 将给定值添加到当前值。
     */
    public long generate(String key, int increment) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.addAndGet(increment);
    }

    /**
     * @param key 生成主键key
     * @param increment 自增值
     * @param expireTime 过期时间
     */
    public long generate(String key, int increment, Date expireTime) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        atomicLong.expireAt(expireTime);
        return atomicLong.addAndGet(increment);
    }

    /**
     * 根据业务key, 长度, 获取key, 以日期作为前缀
     * <p>
     *     key = order, length = 5 ,当天日期2050年1月1日
     *     结果: 2050010100001
     * </p>
     * @param key 生成主键key
     * @param length 自增值+补零长度
     * @return
     */
    public String generateId(String key, Integer length) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);

        long num = atomicLong.incrementAndGet();
        atomicLong.expireAt(getTodayEndTime());
        return getToday() +  String.format("%0" + length + "d", num);
    }

    /**
     * 根据业务key, 获取key, 以日期作为前缀
     * <p>
     *     key = order, length = 5 ,当天日期2050年1月1日
     *     结果: 2050010100001
     * </p>
     * @param key 生成主键key
     * @return
     */
    public String nextStrId(String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        long num = atomicLong.incrementAndGet();
        atomicLong.expireAt(getTodayEndTime());
        return getToday() +  String.format("%0" + 5 + "d", num);
    }

    /**
     * 根据业务key, 获取key, 以日期作为前缀
     * <p>
     *     key = order, length = 5 ,当天日期2050年1月1日
     *     结果: 2050010100001
     * </p>
     * @param key 生成主键key
     * @return
     */
    public Long nextId(String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        long num = atomicLong.incrementAndGet();
        atomicLong.expireAt(getTodayEndTime());
        return Long.parseLong(getToday() +  String.format("%0" + 5 + "d", num));
    }


    /**
     * getTodayEndTime 获取今日最后的时间
     */
    private static Date getTodayEndTime() {
        Calendar todayEnd = Calendar.getInstance();
        todayEnd.set(Calendar.HOUR_OF_DAY, 23);
        todayEnd.set(Calendar.MINUTE, 59);
        todayEnd.set(Calendar.SECOND, 59);
        todayEnd.set(Calendar.MILLISECOND, 999);
        return todayEnd.getTime();
    }

    /**
     * getTodayEndTime 今天的日期格式: 20190101
     */
    private static String getToday() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(new Date());
    }

}
